package br.com.foxinline.servico;

import br.com.foxinline.enums.AplicacaoSelo;
import br.com.foxinline.enums.Relatorio;
import br.com.foxinline.modelo.*;
import br.com.foxinline.utilitario.Caracteres;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.Query;


/**
 *
 * @author cadomeireles
 */
@Stateless
public class ProtocoloServico extends ServicoGenerico<Protocolo> {

    @EJB
    CartorioServico cartorioServico;    

    public ProtocoloServico() {
        super(Protocolo.class);
    }

    public List<Protocolo> pesquisar(Protocolo protocolo) {
        String sql = "select protocolo from Protocolo protocolo join protocolo.cliente cliente where protocolo.ativo = true";

        if (protocolo.getId() != null) {
            sql += " and protocolo.id = " + protocolo.getId();
        }

        if (protocolo.getTipoProtocolo() != null) {
            sql += " and protocolo.tipoProtocolo = :tipoProtocolo";
        }
        
        if (protocolo.getDataCadastro() != null) {
            sql += " and protocolo.dataCadastro = :data";
        }

        if (protocolo.getCliente().getNome() != null && !protocolo.getCliente().getNome().isEmpty()) {
            sql += " and lower(cliente.nome) like '%" + protocolo.getCliente().getNome().toLowerCase()  + "%'";
        }

        if (protocolo.getCliente().getCpf() != null && !protocolo.getCliente().getCpf().isEmpty()) {
            sql += " and lower(cliente.cpf) like '%" +  Caracteres.removecaracter(protocolo.getCliente().getCpf()) + "%'";
        }

        Query query = getEntityManager().createQuery(sql);
        
        if (protocolo.getDataCadastro() != null && protocolo.getDataCadastro() != null) {
            query.setParameter("data", protocolo.getDataCadastro());
        }
        
        if (protocolo.getTipoProtocolo() != null) {
            query.setParameter("tipoProtocolo", protocolo.getTipoProtocolo());
        }        
        
        return query.getResultList();
    }
    
    public Protocolo pesquisarPorCodigo(Protocolo protocolo) {
        String sql = "select protocolo from Protocolo protocolo where protocolo.ativo = true and protocolo.id = " + protocolo.getId();

        Query query = getEntityManager().createQuery(sql);

        return (Protocolo) query.getSingleResult();
    }
    
    public List<ProtocoloItem> obterItens(Protocolo protocolo) {
        String sql = "select item from Protocolo protocolo join protocolo.protocoloItems item where protocolo = :protocolo";

        Query query = getEntityManager().createQuery(sql);
        if (protocolo != null && protocolo.getId() != null) {
            query.setParameter("protocolo", protocolo);
        }
        return query.getResultList();
    }

    public Parcela obterParcelaAVista(Protocolo protocolo) {
        String sql = "select parcela from Protocolo protocolo join protocolo.parcelas parcela where protocolo = :protocolo";

        Query query = getEntityManager().createQuery(sql);
        if (protocolo != null && protocolo.getId() != null) {
            query.setParameter("protocolo", protocolo);
        }
        
        return (Parcela) query.getSingleResult();
    }

    public List<Parcela> obterParcelas(Protocolo protocolo) {
        String sql = "select parcela from Protocolo protocolo join protocolo.parcelas parcela where protocolo = :protocolo";

        Query query = getEntityManager().createQuery(sql);
        
        if (protocolo != null && protocolo.getId() != null) {
            query.setParameter("protocolo", protocolo);
        }
        
        return query.getResultList();
    }
    
    public Selo sugerirSelo(TipoSelo tipo, List<Selo> selosTemporarios) {
        String sql = "select selo from Selo selo where selo.tipoSelo = :tipoSelo and selo.distribuido = true and selo.protocolado = false";

        if (selosTemporarios.size() > 0) {
            String ids = new String();

            for (int i = 0; i < selosTemporarios.size(); i++) {
                ids += selosTemporarios.get(i).getId();
                if (i != selosTemporarios.size() - 1) {
                    ids += ", ";
                }
            }
            
            sql += " and selo.id not in (" + ids + ")";
        }        
        
        sql += " order by selo.id";
        
        Query query = getEntityManager().createQuery(sql);
        
        query.setParameter("tipoSelo", tipo);
        
        try {
            return (Selo) query.getResultList().get(0);
        } catch (ArrayIndexOutOfBoundsException e) {
            return new Selo();
        }        
    }
    
    public Selo sugerirSeloArquivamento(List<Selo> selosTemporarios) {

        String sql = "select selo from Selo selo where selo.tipoSelo.aplicacao like '"+ AplicacaoSelo.ARQUIVAMENTO.name() +"' and selo.distribuido = true and selo.protocolado = false";

        if (selosTemporarios.size() > 0) {
            String ids = new String();

            for (int i = 0; i < selosTemporarios.size(); i++) {
                ids += selosTemporarios.get(i).getId();
                if (i != selosTemporarios.size() - 1) {
                    ids += ", ";
                }
            }

            sql += " and selo.id not in (" + ids + ")";
        }        

        sql += " order by selo.id";        
        
        Query query = getEntityManager().createQuery(sql);
        
        try {
            return (Selo) query.getResultList().get(0);
        } catch (ArrayIndexOutOfBoundsException e) {
            return new Selo();
        }

    }    

    public Selo sugerirSeloGratuidade(List<Selo> selosTemporarios) {
        String sql = "select selo from Selo selo where selo.tipoSelo.aplicacao like '"+ AplicacaoSelo.GRATUIDADE.name() +"' and selo.protocolado = false";

        if (selosTemporarios.size() > 0) {
            String ids = new String();

            for (int i = 0; i < selosTemporarios.size(); i++) {
                ids += selosTemporarios.get(i).getId();
                if (i != selosTemporarios.size() - 1) {
                    ids += ", ";
                }
            }
            
            sql += " and selo.id not in (" + ids + ")";
        }        
        
        sql += " order by selo.id";
        
        Query query = getEntityManager().createQuery(sql);

        try {
            return (Selo) query.getResultList().get(0);
        } catch (ArrayIndexOutOfBoundsException e) {
            return new Selo();
        }
    }    
    
    @Override
    public void deletar(Protocolo protocolo) {
        protocolo.setAtivo(false);
        super.atualizar(protocolo);
    }

    public void gerarRecibo(Protocolo protocolo, BigDecimal valorTotal, List<ProtocoloItem> itens) {

        RelatorioServico relatorioServico = new RelatorioServico();

        HashMap<String, Object> parametros = new HashMap<String, Object>();

        relatorioCabecalho(parametros);

        Locale local = new Locale("pt", "BR");
        DateFormat dateFormat = new SimpleDateFormat("dd 'de' MMMM 'de' yyyy", local);

        parametros.put("protocolo", String.valueOf(protocolo.getCodigo()) );
        parametros.put("cliente", protocolo.getCliente().getNome());
        parametros.put("data", dateFormat.format(protocolo.getDataProtocolo()));
        parametros.put("cpf", adicionarMascaraCPF(protocolo.getCliente().getCpf()));

        NumberFormat numberFormat = NumberFormat.getCurrencyInstance(local);

        parametros.put("valorTotal", numberFormat.format(valorTotal));

        parametros.put("itens", itens);

        parametros.put("SUBREPORT_DIR", "br/com/foxinline/relatorio/");

        relatorioServico.gerarRelatorio(parametros, null, Relatorio.RECIBO);

    }

    private void relatorioCabecalho(HashMap<String, Object> parametros) {
        Cartorio cartorio = cartorioServico.obterCartorio();
        Endereco endereco = cartorio.getEndereco();

        parametros.put("nomeCartorio", cartorio.getRazaoSocial());
        parametros.put("titular", cartorio.getTitular().getNome());
        parametros.put("enderecoCartorio", endereco.getTipoLogradouro().getNome() + " " + endereco.getLogradouro() + ", " + endereco.getBairro().getNome());
        parametros.put("numeroCartorio", endereco.getNumero());
        parametros.put("cidadeCartorio", endereco.getCidade().getNome());
        parametros.put("estadoCartorio", endereco.getCidade().getEstado().getNome());
    }    

    public String adicionarMascaraCPF(String string) {
        return Caracteres.adicionarMascara(string, Caracteres.cpfMask);
    }

}
